//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension OAM {
    // MARK: Enums

    public enum ResourceType: String, CustomStringConvertible, Codable, _SotoSendable {
        case awsCloudwatchMetric = "AWS::CloudWatch::Metric"
        case awsLogsLoggroup = "AWS::Logs::LogGroup"
        case awsXrayTrace = "AWS::XRay::Trace"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct CreateLinkInput: AWSEncodableShape {
        /// Specify a friendly human-readable name to use to identify this source account when you are viewing data from it in the monitoring account. You can use a custom label or use the following variables:    $AccountName is the name of the account    $AccountEmail is the globally unique email address of the account    $AccountEmailNoDomain is the email address of the account without the domain name
        public let labelTemplate: String
        /// An array of strings that define which types of data that the source account shares with the monitoring account.
        public let resourceTypes: [ResourceType]
        /// The ARN of the sink to use to create this link. You can use ListSinks to find the ARNs of sinks. For more information about sinks, see CreateSink.
        public let sinkIdentifier: String
        /// Assigns one or more tags (key-value pairs) to the link.  Tags can help you organize and categorize your resources. You can also use them to scope user permissions by granting a user permission to access or change only resources with certain tag values. For more information about using tags to control access, see Controlling access to Amazon Web Services resources using tags.
        public let tags: [String: String]?

        public init(labelTemplate: String, resourceTypes: [ResourceType], sinkIdentifier: String, tags: [String: String]? = nil) {
            self.labelTemplate = labelTemplate
            self.resourceTypes = resourceTypes
            self.sinkIdentifier = sinkIdentifier
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.labelTemplate, name: "labelTemplate", parent: name, max: 64)
            try self.validate(self.labelTemplate, name: "labelTemplate", parent: name, min: 1)
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, max: 50)
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, min: 1)
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case labelTemplate = "LabelTemplate"
            case resourceTypes = "ResourceTypes"
            case sinkIdentifier = "SinkIdentifier"
            case tags = "Tags"
        }
    }

    public struct CreateLinkOutput: AWSDecodableShape {
        /// The ARN of the link that is newly created.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the link ARN.
        public let id: String?
        /// The label that you assigned to this link. If the labelTemplate includes variables, this field displays the variables resolved to their actual values.
        public let label: String?
        /// The exact label template that you specified, with the variables not resolved.
        public let labelTemplate: String?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that is used for this link.
        public let sinkArn: String?
        /// The tags assigned to the link.
        public let tags: [String: String]?

        public init(arn: String? = nil, id: String? = nil, label: String? = nil, labelTemplate: String? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.labelTemplate = labelTemplate
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case labelTemplate = "LabelTemplate"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
            case tags = "Tags"
        }
    }

    public struct CreateSinkInput: AWSEncodableShape {
        /// A name for the sink.
        public let name: String
        /// Assigns one or more tags (key-value pairs) to the link.  Tags can help you organize and categorize your resources. You can also use them to scope user permissions by granting a user permission to access or change only resources with certain tag values. For more information about using tags to control access, see Controlling access to Amazon Web Services resources using tags.
        public let tags: [String: String]?

        public init(name: String, tags: [String: String]? = nil) {
            self.name = name
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9_\\.\\-]{1,255}$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case name = "Name"
            case tags = "Tags"
        }
    }

    public struct CreateSinkOutput: AWSDecodableShape {
        /// The ARN of the sink that is newly created.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The name of the sink.
        public let name: String?
        /// The tags assigned to the sink.
        public let tags: [String: String]?

        public init(arn: String? = nil, id: String? = nil, name: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.name = name
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case name = "Name"
            case tags = "Tags"
        }
    }

    public struct DeleteLinkInput: AWSEncodableShape {
        /// The ARN of the link to delete.
        public let identifier: String

        public init(identifier: String) {
            self.identifier = identifier
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
        }
    }

    public struct DeleteLinkOutput: AWSDecodableShape {
        public init() {}
    }

    public struct DeleteSinkInput: AWSEncodableShape {
        /// The ARN of the sink to delete.
        public let identifier: String

        public init(identifier: String) {
            self.identifier = identifier
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
        }
    }

    public struct DeleteSinkOutput: AWSDecodableShape {
        public init() {}
    }

    public struct GetLinkInput: AWSEncodableShape {
        /// The ARN of the link to retrieve information for.
        public let identifier: String

        public init(identifier: String) {
            self.identifier = identifier
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
        }
    }

    public struct GetLinkOutput: AWSDecodableShape {
        /// The ARN of the link.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the link ARN.
        public let id: String?
        /// The label that you assigned to this link, with the variables resolved to their actual values.
        public let label: String?
        /// The exact label template that was specified when the link was created, with the template variables not resolved.
        public let labelTemplate: String?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that is used for this link.
        public let sinkArn: String?
        /// The tags assigned to the link.
        public let tags: [String: String]?

        public init(arn: String? = nil, id: String? = nil, label: String? = nil, labelTemplate: String? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.labelTemplate = labelTemplate
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case labelTemplate = "LabelTemplate"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
            case tags = "Tags"
        }
    }

    public struct GetSinkInput: AWSEncodableShape {
        /// The ARN of the sink to retrieve information for.
        public let identifier: String

        public init(identifier: String) {
            self.identifier = identifier
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
        }
    }

    public struct GetSinkOutput: AWSDecodableShape {
        /// The ARN of the sink.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The name of the sink.
        public let name: String?
        /// The tags assigned to the sink.
        public let tags: [String: String]?

        public init(arn: String? = nil, id: String? = nil, name: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.name = name
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case name = "Name"
            case tags = "Tags"
        }
    }

    public struct GetSinkPolicyInput: AWSEncodableShape {
        /// The ARN of the sink to retrieve the policy of.
        public let sinkIdentifier: String

        public init(sinkIdentifier: String) {
            self.sinkIdentifier = sinkIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case sinkIdentifier = "SinkIdentifier"
        }
    }

    public struct GetSinkPolicyOutput: AWSDecodableShape {
        /// The policy that you specified, in JSON format.
        public let policy: String?
        /// The ARN of the sink.
        public let sinkArn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let sinkId: String?

        public init(policy: String? = nil, sinkArn: String? = nil, sinkId: String? = nil) {
            self.policy = policy
            self.sinkArn = sinkArn
            self.sinkId = sinkId
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case sinkArn = "SinkArn"
            case sinkId = "SinkId"
        }
    }

    public struct ListAttachedLinksInput: AWSEncodableShape {
        /// Limits the number of returned links to the specified number.
        public let maxResults: Int?
        /// The token for the next set of items to return. You received this token from a previous call.
        public let nextToken: String?
        /// The ARN of the sink that you want to retrieve links for.
        public let sinkIdentifier: String

        public init(maxResults: Int? = nil, nextToken: String? = nil, sinkIdentifier: String) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.sinkIdentifier = sinkIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 1000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
            case sinkIdentifier = "SinkIdentifier"
        }
    }

    public struct ListAttachedLinksItem: AWSDecodableShape {
        /// The label that was assigned to this link at creation, with the variables resolved to their actual values.
        public let label: String?
        /// The ARN of the link.
        public let linkArn: String?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?

        public init(label: String? = nil, linkArn: String? = nil, resourceTypes: [String]? = nil) {
            self.label = label
            self.linkArn = linkArn
            self.resourceTypes = resourceTypes
        }

        private enum CodingKeys: String, CodingKey {
            case label = "Label"
            case linkArn = "LinkArn"
            case resourceTypes = "ResourceTypes"
        }
    }

    public struct ListAttachedLinksOutput: AWSDecodableShape {
        /// An array of structures that contain the information about the attached links.
        public let items: [ListAttachedLinksItem]
        /// The token to use when requesting the next set of links.
        public let nextToken: String?

        public init(items: [ListAttachedLinksItem], nextToken: String? = nil) {
            self.items = items
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case items = "Items"
            case nextToken = "NextToken"
        }
    }

    public struct ListLinksInput: AWSEncodableShape {
        /// Limits the number of returned links to the specified number.
        public let maxResults: Int?
        /// The token for the next set of items to return. You received this token from a previous call.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 5)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListLinksItem: AWSDecodableShape {
        /// The ARN of the link.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the link ARN.
        public let id: String?
        /// The label that was assigned to this link at creation, with the variables resolved to their actual values.
        public let label: String?
        /// The resource types supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that this link is attached to.
        public let sinkArn: String?

        public init(arn: String? = nil, id: String? = nil, label: String? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
        }
    }

    public struct ListLinksOutput: AWSDecodableShape {
        /// An array of structures that contain the information about the returned links.
        public let items: [ListLinksItem]
        /// The token to use when requesting the next set of links.
        public let nextToken: String?

        public init(items: [ListLinksItem], nextToken: String? = nil) {
            self.items = items
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case items = "Items"
            case nextToken = "NextToken"
        }
    }

    public struct ListSinksInput: AWSEncodableShape {
        /// Limits the number of returned links to the specified number.
        public let maxResults: Int?
        /// The token for the next set of items to return. You received this token from a previous call.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListSinksItem: AWSDecodableShape {
        /// The ARN of the sink.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The name of the sink.
        public let name: String?

        public init(arn: String? = nil, id: String? = nil, name: String? = nil) {
            self.arn = arn
            self.id = id
            self.name = name
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case name = "Name"
        }
    }

    public struct ListSinksOutput: AWSDecodableShape {
        /// An array of structures that contain the information about the returned sinks.
        public let items: [ListSinksItem]
        /// The token to use when requesting the next set of sinks.
        public let nextToken: String?

        public init(items: [ListSinksItem], nextToken: String? = nil) {
            self.items = items
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case items = "Items"
            case nextToken = "NextToken"
        }
    }

    public struct ListTagsForResourceInput: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("ResourceArn"))
        ]

        /// The ARN of the  resource that you want to view tags for. The ARN format of a sink is arn:aws:oam:Region:account-id:sink/sink-id   The ARN format of a link is arn:aws:oam:Region:account-id:link/link-id   For more information about ARN format, see CloudWatch Logs resources and operations.  Unlike tagging permissions in other Amazon Web Services services, to retrieve the list of tags for links or sinks you must have the oam:RequestTag permission. The aws:ReguestTag permission does not allow you to tag and untag links and sinks.
        public let resourceArn: String

        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(\\w|-)+:oam:.+:.+:.+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceOutput: AWSDecodableShape {
        /// The list of tags associated with the requested resource.&gt;
        public let tags: [String: String]?

        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "Tags"
        }
    }

    public struct PutSinkPolicyInput: AWSEncodableShape {
        /// The JSON policy to use. If you are updating an existing policy, the entire existing policy is replaced by what you specify here. The policy must be in JSON string format with quotation marks escaped and no newlines. For examples of different types of policies, see the Examples section on this page.
        public let policy: String
        /// The ARN of the sink to attach this policy to.
        public let sinkIdentifier: String

        public init(policy: String, sinkIdentifier: String) {
            self.policy = policy
            self.sinkIdentifier = sinkIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.sinkIdentifier, name: "sinkIdentifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case sinkIdentifier = "SinkIdentifier"
        }
    }

    public struct PutSinkPolicyOutput: AWSDecodableShape {
        /// The policy that you specified.
        public let policy: String?
        /// The ARN of the sink.
        public let sinkArn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let sinkId: String?

        public init(policy: String? = nil, sinkArn: String? = nil, sinkId: String? = nil) {
            self.policy = policy
            self.sinkArn = sinkArn
            self.sinkId = sinkId
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "Policy"
            case sinkArn = "SinkArn"
            case sinkId = "SinkId"
        }
    }

    public struct TagResourceInput: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("ResourceArn"))
        ]

        /// The ARN of the  resource that you're adding tags to. The ARN format of a sink is arn:aws:oam:Region:account-id:sink/sink-id   The ARN format of a link is arn:aws:oam:Region:account-id:link/link-id   For more information about ARN format, see CloudWatch Logs resources and operations.
        public let resourceArn: String
        /// The list of key-value pairs to associate with the resource.
        public let tags: [String: String]

        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(\\w|-)+:oam:.+:.+:.+")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "Tags"
        }
    }

    public struct TagResourceOutput: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceInput: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("ResourceArn")),
            AWSMemberEncoding(label: "tagKeys", location: .querystring("tagKeys"))
        ]

        /// The ARN of the resource that you're removing tags from. The ARN format of a sink is arn:aws:oam:Region:account-id:sink/sink-id   The ARN format of a link is arn:aws:oam:Region:account-id:link/link-id   For more information about ARN format, see CloudWatch Logs resources and operations.
        public let resourceArn: String
        /// The list of tag keys to remove from the resource.
        public let tagKeys: [String]

        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(\\w|-)+:oam:.+:.+:.+")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
            }
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceOutput: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateLinkInput: AWSEncodableShape {
        /// The ARN of the link that you want to update.
        public let identifier: String
        /// An array of strings that define which types of data that the source account will send to the monitoring account. Your input here replaces the current set of data types that are shared.
        public let resourceTypes: [ResourceType]

        public init(identifier: String, resourceTypes: [ResourceType]) {
            self.identifier = identifier
            self.resourceTypes = resourceTypes
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-zA-Z0-9][a-zA-Z0-9_:\\.\\-\\/]{0,2047}$")
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, max: 50)
            try self.validate(self.resourceTypes, name: "resourceTypes", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case identifier = "Identifier"
            case resourceTypes = "ResourceTypes"
        }
    }

    public struct UpdateLinkOutput: AWSDecodableShape {
        /// The ARN of the link that you have updated.
        public let arn: String?
        /// The random ID string that Amazon Web Services generated as part of the sink ARN.
        public let id: String?
        /// The label assigned to this link, with the variables resolved to their actual values.
        public let label: String?
        /// The exact label template that was specified when the link was created, with the template variables not resolved.
        public let labelTemplate: String?
        /// The resource types now supported by this link.
        public let resourceTypes: [String]?
        /// The ARN of the sink that is used for this link.
        public let sinkArn: String?
        /// The tags assigned to the link.
        public let tags: [String: String]?

        public init(arn: String? = nil, id: String? = nil, label: String? = nil, labelTemplate: String? = nil, resourceTypes: [String]? = nil, sinkArn: String? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.id = id
            self.label = label
            self.labelTemplate = labelTemplate
            self.resourceTypes = resourceTypes
            self.sinkArn = sinkArn
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case id = "Id"
            case label = "Label"
            case labelTemplate = "LabelTemplate"
            case resourceTypes = "ResourceTypes"
            case sinkArn = "SinkArn"
            case tags = "Tags"
        }
    }
}

// MARK: - Errors

/// Error enum for OAM
public struct OAMErrorType: AWSErrorType {
    enum Code: String {
        case conflictException = "ConflictException"
        case internalServiceFault = "InternalServiceFault"
        case invalidParameterException = "InvalidParameterException"
        case missingRequiredParameterException = "MissingRequiredParameterException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case tooManyTagsException = "TooManyTagsException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize OAM
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// A resource was in an inconsistent state during an update or a deletion.
    public static var conflictException: Self { .init(.conflictException) }
    /// Unexpected error while processing the request. Retry the request.
    public static var internalServiceFault: Self { .init(.internalServiceFault) }
    /// A parameter is specified incorrectly.
    public static var invalidParameterException: Self { .init(.invalidParameterException) }
    /// A required parameter is missing from the request.
    public static var missingRequiredParameterException: Self { .init(.missingRequiredParameterException) }
    /// The request references a resource that does not exist.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// The request would cause a service quota to be exceeded.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// A resource can have no more than 50 tags.
    public static var tooManyTagsException: Self { .init(.tooManyTagsException) }
    /// The value of a parameter in the request caused an error.
    public static var validationException: Self { .init(.validationException) }
}

extension OAMErrorType: Equatable {
    public static func == (lhs: OAMErrorType, rhs: OAMErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension OAMErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
